home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Graphics⁄Sound / RTrace-1.0-src / textrace.c < prev    next >
Text File  |  1992-09-06  |  25KB  |  1,266 lines

  1. /*
  2.  * Copyright (c) 1992 Pedro Borges, Paulo Almeida, INESC-Norte.
  3.  * All rights reserved.
  4.  *
  5.  * This code received contributions from the following people:
  6.  *
  7.  *  Roman Kuchkuda      - basic ray tracer
  8.  *  Mark VandeWettering - MTV ray tracer
  9.  *  Augusto Sousa       - overall, shading model
  10.  *
  11.  * Redistribution and use in source and binary forms are permitted
  12.  * provided that the above copyright notice and this paragraph are
  13.  * duplicated in all such forms and that any documentation,
  14.  * advertising materials, and other materials related to such
  15.  * distribution and use acknowledge that the software was developed
  16.  * by Antonio Costa, at INESC-Norte. The name of the author and
  17.  * INESC-Norte may not be used to endorse or promote products derived
  18.  * from this software without specific prior written permission.
  19.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  20.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  21.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  22.  */
  23. #include "textrace.h"
  24.  
  25. /**********************************************************************
  26.  *    RAY TRACING - Version 7.3.2                                     *
  27.  *                                                                    *
  28.  *    MADE BY: Pedro Borges, Paulo Almeida, INESC-Norte, June 1992    *
  29.  *    MODIFIED BY: Antonio Costa, INESC-Norte, August 1992            *
  30.  **********************************************************************/
  31.  
  32. #ifndef __STDC__
  33. #define ERR_MAX 16
  34. #endif
  35.  
  36. static void
  37. vcpy(u, v)
  38.   xyz_ptr      u, v;
  39. {
  40.   u->x = v->x;
  41.   u->y = v->y;
  42.   u->z = v->z;
  43. }
  44.  
  45. static void
  46. vadd(u, v, w)
  47.   xyz_ptr      u, v, w;
  48. {
  49.   u->x = v->x + w->x;
  50.   u->y = v->y + w->y;
  51.   u->z = v->z + w->z;
  52. }
  53.  
  54. static void
  55. vsub(u, v, w)
  56.   xyz_ptr      u, v, w;
  57. {
  58.   u->x = v->x - w->x;
  59.   u->y = v->y - w->y;
  60.   u->z = v->z - w->z;
  61. }
  62.  
  63. static void
  64. vmul(u, v, r)
  65.   xyz_ptr      u, v;
  66.   real          r;
  67. {
  68.   u->x = v->x * r;
  69.   u->y = v->y * r;
  70.   u->z = v->z * r;
  71. }
  72.  
  73. static void
  74. vmuladd(u, v, r)
  75.   xyz_ptr      u, v;
  76.   real          r;
  77. {
  78.   u->x += v->x * r;
  79.   u->y += v->y * r;
  80.   u->z += v->z * r;
  81. }
  82.  
  83. static void
  84. vtransf(u, ax, v)
  85.   xyz_ptr      u;
  86.   xyz_axes     *ax;
  87.   xyz_ptr      v;
  88. {
  89.   vmul(u, &ax->x_v, v->x);
  90.   vmuladd(u, &ax->y_v, v->y);
  91.   vmuladd(u, &ax->z_v, v->z);
  92. }
  93.  
  94. static void
  95. vminmax(min, max, v)
  96.   xyz_ptr      min, max, v;
  97. {
  98.   if (v->x < min->x)
  99.     min->x = v->x;
  100.   else if (v->x > max->x)
  101.     max->x = v->x;
  102.   if (v->y < min->y)
  103.     min->y = v->y;
  104.   else if (v->y > max->y)
  105.     max->y = v->y;
  106.   if (v->z < min->z)
  107.     min->z = v->z;
  108.   else if (v->z > max->z)
  109.     max->z = v->z;
  110. }
  111.  
  112. real 
  113. vpint(u, v)
  114.   xyz_ptr      u, v;
  115. {
  116.   return u->x * v->x + u->y * v->y + u->z * v->z;
  117. }
  118.  
  119. real 
  120. vmod(v)
  121.   xyz_ptr      v;
  122. {
  123.   return sqrt(v->x * v->x + v->y * v->y + v->z * v->z);
  124. }
  125.  
  126. int 
  127. vnormalize(v)
  128.   xyz_ptr      v;
  129. {
  130.   real            r;
  131.  
  132.   r = vmod(v);
  133.   if (r < TINY)
  134.     return 0;
  135.   vmul(v, v, 1.0 / r);
  136.   return 1;
  137. }
  138.  
  139. real 
  140. vinvmat(x, y, z, ox, oy, oz)
  141.   xyz_ptr      x, y, z, ox, oy, oz;
  142. {
  143.   real            det, idet;
  144.  
  145.   ox->x = y->y * z->z - y->z * z->y;
  146.   oy->x = y->z * z->x - y->x * z->z;
  147.   oz->x = y->x * z->y - y->y * z->x;
  148.   det = x->x * ox->x + x->y * oy->x + x->z * oz->x;
  149.   if (fabs(det) < TINY)
  150.     return 0.0;
  151.   ox->y = x->z * z->y - x->y * z->z;
  152.   oy->y = x->x * z->z - x->z * z->x;
  153.   oz->y = x->y * z->x - x->x * z->y;
  154.   ox->z = x->y * y->z - x->z * y->y;
  155.   oy->z = x->z * y->x - x->x * y->z;
  156.   oz->z = x->x * y->y - x->y * y->x;
  157.   idet = 1 / det;
  158.   vmul(ox, ox, idet);
  159.   vmul(oy, oy, idet);
  160.   vmul(oz, oz, idet);
  161.   return det;
  162. }
  163.  
  164. static int
  165. err_line(fp)
  166.   FILE         *fp;
  167. {
  168.   int             pos, nl, i;
  169.  
  170.   nl = 1;
  171.   pos = ftell(fp);
  172.   rewind(fp);
  173.   for (i = 0; i < pos - 1; i++)
  174.     if (getc(fp) == '\n')
  175.       nl++;
  176.   return nl;
  177. }
  178.  
  179. static void
  180. prt_arr(s)
  181.   char         *s[];
  182. {
  183.   while (*s)
  184.     fprintf(stderr, "%s", *s++);
  185.   fprintf(stderr, "\n");
  186. }
  187.  
  188. static void
  189. errorfn(s, fp, fn)
  190.   char         *s[];
  191.   FILE         *fp;
  192.   char         *fn;
  193. {
  194.   fprintf(stderr, "Text error in %s file at line %d: ", fn, err_line(fp));
  195.   prt_arr(s);
  196.   exit(1);
  197. }
  198.  
  199. static void
  200. error(s)
  201.   char         *s[];
  202. {
  203.   fprintf(stderr, "Text error: ");
  204.   prt_arr(s);
  205.   exit(1);
  206. }
  207.  
  208. void           *
  209. alloc(t)
  210.   unsigned      t;
  211. {
  212.   void           *p;
  213. #ifdef __STDC__
  214.   char           *err[] =
  215.   {"Memory allocation error ", 0};
  216. #else
  217.   char           *err[ERR_MAX];
  218.  
  219.   err[0] = "Memory allocation error ";
  220.   err[1] = 0;
  221. #endif
  222.  
  223.   p = (void *) malloc(t);
  224.   if (!p)
  225.     error(err);
  226.   return p;
  227. }
  228.  
  229. static FILE    *
  230. cfopen(file, mode)
  231.   char         *file, *mode;
  232. {
  233.   FILE           *fp;
  234. #ifdef __STDC__
  235.   char           *err[] =
  236.   {"Open error in file ", 0, 0};
  237. #else
  238.   char           *err[ERR_MAX];
  239.  
  240.   err[0] = "Open error in file ";
  241.   err[1] = 0;
  242.   err[2] = 0;
  243. #endif
  244.  
  245.   fp = fopen(file, mode);
  246.   if (!fp)
  247.   {
  248.     err[1] = file;
  249.     error(err);
  250.   }
  251.   return fp;
  252. }
  253.  
  254. /***** Global variables *****/
  255. static file_ptr fp;
  256. static xyz_axes *orient_ptr = 0;
  257. static xyz_ptr  size_ptr = 0;
  258. static real     space = NULSP;
  259. static font    *fonts_ptr = 0, *font_ptr = 0;
  260. static code    *code_ptr = 0;
  261. static char    *codename = 0;
  262. static char     buffer[BUFFERSIZE];
  263. static char     ifname[] = "input";
  264.  
  265. static void
  266. skip_space(fp)
  267.   FILE         *fp;
  268. {
  269.   int             c;
  270.  
  271.   do
  272.   {
  273.     c = getc(fp);
  274.   } while (isspace(c));
  275.   ungetc(c, fp);
  276. }
  277.  
  278. static void
  279. expect(s, fp, fname)
  280.   char         *s;
  281.   FILE         *fp;
  282.   char         *fname;
  283. {
  284.   char            b[100];
  285.   int             i;
  286. #ifdef __STDC__
  287.   char           *err[] =
  288.   {"Expected '", 0, "', found '", 0, "'", 0};
  289. #else
  290.   char           *err[ERR_MAX];
  291.  
  292.   err[0] = "Expected '";
  293.   err[1] = 0;
  294.   err[2] = "', found '";
  295.   err[3] = 0;
  296.   err[4] = "'";
  297.   err[5] = 0;
  298. #endif
  299.  
  300.   i = 0;
  301.   skip_space(fp);
  302.   while (s[i])
  303.   {
  304.     if ((b[i] = getc(fp)) != s[i])
  305.     {
  306.       b[++i] = 0;
  307.       err[1] = s;
  308.       err[3] = b;
  309.       errorfn(err, fp, fname);
  310.     }
  311.     i++;
  312.   }
  313. }
  314.  
  315. static char    *
  316. get_ident(fp, fname)
  317.   FILE         *fp;
  318.   char         *fname;
  319. {
  320.   char           *b;
  321.   int             c, i;
  322. #ifdef __STDC__
  323.   char           *err[] =
  324.   {"Character name too long", 0};
  325. #else
  326.   char           *err[ERR_MAX];
  327.  
  328.   err[0] = "Character name too long";
  329.   err[1] = 0;
  330. #endif
  331.  
  332.   b = buffer;
  333.   skip_space(fp);
  334.   i = 0;
  335.   while (c = getc(fp), !isspace(c) && c != EOF && i < BUFFERSIZE - 1)
  336.     b[i++] = c;
  337.   if (i == BUFFERSIZE - 1)
  338.     errorfn(err, fp, fname);
  339.   b[i] = 0;
  340.   return b;
  341. }
  342.  
  343. static          real
  344. get_real(fp, fname)
  345.   FILE         *fp;
  346.   char         *fname;
  347. {
  348.   real            r;
  349. #ifdef __STDC__
  350.   char           *err[] =
  351.   {"Real number expected", 0};
  352. #else
  353.   char           *err[ERR_MAX];
  354.  
  355.   err[0] = "Real number expected";
  356.   err[1] = 0;
  357. #endif
  358.  
  359.   if (fscanf(fp, REALCONV, &r) < 1)
  360.     errorfn(err, fp, fname);
  361.   return r;
  362. }
  363.  
  364. static int
  365. get_int(fp, fname)
  366.   FILE         *fp;
  367.   char         *fname;
  368. {
  369.   int             i;
  370. #ifdef __STDC__
  371.   char           *err[] =
  372.   {"Integer expected", 0};
  373. #else
  374.   char           *err[ERR_MAX];
  375.  
  376.   err[0] = "Integer expected";
  377.   err[1] = 0;
  378. #endif
  379.  
  380.   if (fscanf(fp, "%d", &i) < 1)
  381.     errorfn(err, fp, fname);
  382.   return i;
  383. }
  384.  
  385. static void
  386. get_vector(vec_ptr)
  387.   xyz_ptr      vec_ptr;
  388. {
  389.   vec_ptr->x = get_real(fp, ifname);
  390.   vec_ptr->y = get_real(fp, ifname);
  391.   vec_ptr->z = get_real(fp, ifname);
  392. }
  393.  
  394. static char    *
  395. get_name_from_code(c)
  396.   int          c;
  397. {
  398.   code           *cp;
  399.   char            a[10];
  400. #ifdef __STDC__
  401.   char           *err[] =
  402.   {"Character code ", 0, " missing in encoding file ", 0, 0};
  403. #else
  404.   char           *err[ERR_MAX];
  405.  
  406.   err[0] = "Character code ";
  407.   err[1] = 0;
  408.   err[2] = " missing in encoding file ";
  409.   err[3] = 0;
  410.   err[4] = 0;
  411. #endif
  412.  
  413.   cp = code_ptr;
  414.   while (cp && cp->code != c)
  415.     cp = cp->next;
  416.   if (!cp)
  417.   {
  418.     err[3] = codename;
  419.     sprintf(a, "%d", c);
  420.     err[1] = a;
  421.     error(err);
  422.   }
  423.   return cp->name;
  424. }
  425.  
  426. static char    *
  427. get_name_from_file()
  428. {
  429.   char           *b;
  430.   int             c, i;
  431. #ifdef __STDC__
  432.   char           *err1[] =
  433.   {"End of file unexpected", 0};
  434.   char           *err2[] =
  435.   {"Character name too long", 0};
  436. #else
  437.   char           *err1[ERR_MAX];
  438.   char           *err2[ERR_MAX];
  439.  
  440.   err1[0] = "End of file unexpected";
  441.   err1[1] = 0;
  442.   err2[0] = "Character name too long";
  443.   err2[1] = 0;
  444. #endif
  445.  
  446.   b = buffer;
  447.   i = 0;
  448.   while (c = getc(fp), c != PSNAME && c != EOF && i < BUFFERSIZE - 1)
  449.     b[i++] = c;
  450.   if (c == EOF)
  451.     errorfn(err1, fp, ifname);
  452.   if (i == BUFFERSIZE - 1)
  453.     errorfn(err2, fp, ifname);
  454.   b[i] = 0;
  455.   return b;
  456. }
  457.  
  458. static void
  459. get_char_desc(pdp, fp, fname)
  460.   prismdsc     *pdp;
  461.   FILE         *fp;
  462.   char         *fname;
  463. {
  464.   int             ncc, nc, cc, c;
  465.   ccurve         *cca;
  466.   curve          *ca;
  467.   char           *type;
  468. #ifdef __STDC__
  469.   char           *err[] =
  470.   {"Unknown curve type in font file", 0};
  471. #else
  472.   char           *err[ERR_MAX];
  473.  
  474.   err[0] = "Unknown curve type in font file";
  475.   err[1] = 0;
  476. #endif
  477.  
  478.   pdp->bot = get_real(fp, fname);
  479.   pdp->top = get_real(fp, fname);
  480.   pdp->width = get_real(fp, fname);
  481.   ncc = pdp->n = get_int(fp, fname);
  482.   cca = pdp->ccurve_arr = newa(ccurve, ncc);
  483.   for (cc = 0; cc < ncc; cc++)
  484.   {
  485.     nc = cca[cc].n = get_int(fp, fname);
  486.     ca = cca[cc].curve_arr = newa(curve, nc + 1);
  487.     for (c = 0; c < nc; c++)
  488.     {
  489.       type = get_ident(fp, fname);
  490.       if (!strcmp(type, "l"))
  491.       {
  492.     ca[c].t = 1;
  493.     ca[c].p[0].x = get_real(fp, fname);
  494.     ca[c].p[0].y = get_real(fp, fname);
  495.       } else if (!strcmp(type, "c"))
  496.       {
  497.     ca[c].t = 3;
  498.     ca[c].p[0].x = get_real(fp, fname);
  499.     ca[c].p[0].y = get_real(fp, fname);
  500.     ca[c].p[1].x = get_real(fp, fname);
  501.     ca[c].p[1].y = get_real(fp, fname);
  502.     ca[c].p[2].x = get_real(fp, fname);
  503.     ca[c].p[2].y = get_real(fp, fname);
  504.       } else
  505.     errorfn(err, fp, fname);
  506.     }
  507.     ca[nc].p[0].x = ca[0].p[0].x;
  508.     ca[nc].p[0].y = ca[0].p[0].y;
  509.   }
  510. }
  511.  
  512. static void
  513. get_char_font(chp)
  514.   character     *chp;
  515. {
  516.   font           *fntp;
  517.   FILE           *fp;
  518.   char           *name;
  519.   int             c;
  520. #ifdef __STDC__
  521.   char           *err1[] =
  522.   {"Unexpected character in font file", 0};
  523.   char           *err2[] =
  524.   {"Missing character description of '", 0,
  525.    "' in font file ", 0, 0};
  526. #else
  527.   char           *err1[ERR_MAX];
  528.   char           *err2[ERR_MAX];
  529.  
  530.   err1[0] = "Unexpected character in font file";
  531.   err1[1] = 0;
  532.   err2[0] = "Missing character description of '";
  533.   err2[1] = 0;
  534.   err2[2] = "' in font file ";
  535.   err2[3] = 0;
  536.   err2[4] = 0;
  537. #endif
  538.  
  539.   fntp = font_ptr;
  540.   err2[1] = chp->name;
  541.   err2[3] = fntp->name;
  542.   fp = cfopen(fntp->name, "r");
  543.   while (1)
  544.   {
  545.     skip_space(fp);
  546.     c = getc(fp);
  547.     if (c == EOF)
  548.       error(err2);
  549.     if (c != PSNAME)
  550.       errorfn(err1, fp, fntp->name);
  551.     name = get_ident(fp, fntp->name);
  552.     if (strcmp(name, chp->name))
  553.     {
  554.       while (c = getc(fp), c != PSNAME && c != EOF)
  555.     ;
  556.       if (c == EOF)
  557.     error(err2);
  558.       ungetc(c, fp);
  559.     } else
  560.     {
  561.       get_char_desc(chp->prismdsc_ptr, fp, fntp->name);
  562.       fclose(fp);
  563.       break;
  564.     }
  565.   }
  566. }
  567.  
  568. static prismdsc *
  569. get_prismdsc_ptr(name)
  570.   char         *name;
  571. {
  572.   character      *chp;
  573.  
  574.   chp = font_ptr->ch_ptr;
  575.   while (chp && strcmp(name, chp->name))
  576.     chp = chp->next;
  577.   if (!chp)
  578.   {
  579.     chp = new(character);
  580.     chp->next = font_ptr->ch_ptr;
  581.     font_ptr->ch_ptr = chp;
  582.     chp->name = alloc(strlen(name) + 1);
  583.     strcpy(chp->name, name);
  584.     chp->prismdsc_ptr = new(prismdsc);
  585.     get_char_font(chp);
  586.   }
  587.   return chp->prismdsc_ptr;
  588. }
  589.  
  590. static void
  591. calc_englob(pp, minp, maxp)
  592.   prism         *pp;
  593.   xyz_ptr      minp, maxp;
  594. {
  595.   prismdsc       *pdp;
  596.   xyz_struct      v[2], u, w;
  597.   int             i, j, k;
  598.  
  599.   pdp = pp->prismdsc_ptr;
  600.   v[0].x = 0.0;
  601.   v[1].x = pdp->width * pp->size_ptr->x;
  602.   v[0].y = pdp->bot * pp->size_ptr->y;
  603.   v[1].y = pdp->top * pp->size_ptr->y;
  604.   v[0].z = 0.0;
  605.   v[1].z = pp->size_ptr->z;
  606.   for (i = 0; i < 2; i++)
  607.     for (j = 0; j < 2; j++)
  608.       for (k = 0; k < 2; k++)
  609.       {
  610.     u.x = v[i].x;
  611.     u.y = v[j].y;
  612.     u.z = v[k].z;
  613.     vtransf(&w, pp->orient_ptr, &u);
  614.     if (!i && !j && !k)
  615.     {
  616.       vcpy(minp, &w);
  617.       vcpy(maxp, &w);
  618.     } else
  619.       vminmax(minp, maxp, &w);
  620.       }
  621.   vadd(minp, minp, &pp->position);
  622.   vadd(maxp, maxp, &pp->position);
  623. }
  624.  
  625. static void
  626. update_position(posp, width)
  627.   xyz_ptr      posp;
  628.   real          width;
  629. {
  630.   real            size;
  631.  
  632.   size = size_ptr->x;
  633.   size *= width + space;
  634.   vmuladd(posp, &orient_ptr->x_v, size);
  635. }
  636.  
  637. static void
  638. get_at_text()
  639. {
  640.   prism          *prism_ptr;
  641.   void          **priv_p_p;
  642.   xyz_struct      position;
  643.   xyz_ptr         minp, maxp;
  644.   char           *name;
  645.   int             c;
  646.  
  647.   get_vector(&position);
  648.   expect("\"", fp, ifname);
  649.   while (c = getc(fp), c != '\"')
  650.   {
  651.     if (c == ' ')
  652.     {
  653.       update_position(&position, 0.5);
  654.       continue;
  655.     }
  656.     prism_ptr = new(prism);
  657.     priv_p_p = (void **) create_pp_obj(&minp, &maxp);
  658.     *priv_p_p = (void *) prism_ptr;
  659.     if (c != PSNAME)
  660.       name = get_name_from_code(c);
  661.     else
  662.       name = get_name_from_file();
  663.     prism_ptr->prismdsc_ptr = get_prismdsc_ptr(name);
  664.     prism_ptr->position = position;
  665.     prism_ptr->orient_ptr = orient_ptr;
  666.     prism_ptr->size_ptr = size_ptr;
  667.     calc_englob(prism_ptr, minp, maxp);
  668.     update_position(&position, prism_ptr->prismdsc_ptr->width);
  669.  
  670. #ifdef THINK_C
  671.  
  672.     /* On the mac, we need to track reading of text objects on the progress bar */
  673.     if (status_dialog_visible) set_progress_bar_value(objects);
  674.  
  675. #endif
  676.  
  677.   }
  678. }
  679.  
  680. static void
  681. add_font(name)
  682.   char         *name;
  683. {
  684.   font           *fp;
  685.  
  686.   fp = fonts_ptr;
  687.   while (fp && fp->name != name)
  688.     fp = fp->next;
  689.   if (!fp)
  690.   {
  691.     fp = new(font);
  692.     fp->next = fonts_ptr;
  693.     fonts_ptr = fp;
  694.     fp->ch_ptr = 0;
  695.     fp->name = alloc(strlen(name) + 1);
  696.     strcpy(fp->name, name);
  697.   }
  698.   font_ptr = fp;
  699. }
  700.  
  701. static void
  702. get_encoding_file(fname)
  703.   char         *fname;
  704. {
  705.   FILE           *fp;
  706.   char           *cname;
  707.   code           *cp;
  708.   int             i;
  709. #ifdef __STDC__
  710.   char           *err1[] =
  711.   {"Encoding file read error", 0};
  712.   char           *err2[] =
  713.   {"Unexpected character found in encoding file", 0};
  714. #else
  715.   char           *err1[ERR_MAX];
  716.   char           *err2[ERR_MAX];
  717.  
  718.   err1[0] = "Encoding file read error";
  719.   err1[1] = 0;
  720.   err2[0] = "Unexpected character found in encoding file";
  721.   err2[1] = 0;
  722. #endif
  723.  
  724.   fp = cfopen(fname, "r");
  725.   codename = alloc(strlen(fname) + 1);
  726.   strcpy(codename, fname);
  727.   while (fscanf(fp, "%d", &i) > 0)
  728.   {
  729.     expect("/", fp, fname);
  730.     cname = fgets(buffer, BUFFERSIZE, fp);
  731.     if (!cname)
  732.       errorfn(err1, fp, codename);
  733.     cp = new(code);
  734.     cp->next = code_ptr;
  735.     code_ptr = cp;
  736.     cp->code = i;
  737.     i = strlen(cname);
  738.     cname[i - 1] = 0;
  739.     cp->name = alloc(i);
  740.     strcpy(cp->name, cname);
  741.   }
  742.   if (getc(fp) != EOF)
  743.     errorfn(err2, fp, codename);
  744. }
  745.  
  746. static void
  747. change_encoding_vector(name)
  748.   char         *name;
  749. {
  750.   code           *cp;
  751.  
  752.   if (codename && !strcmp(codename, name))
  753.     return;
  754.   if (codename)
  755.   {
  756.     free(codename);
  757.     while (code_ptr)
  758.     {
  759.       cp = code_ptr;
  760.       free(cp->name);
  761.       code_ptr = code_ptr->next;
  762.       free(cp);
  763.     }
  764.   }
  765.   get_encoding_file(name);
  766. }
  767.  
  768. static char    *
  769. get_com()
  770. {
  771.   int             nl, c;
  772.   char           *p, *b;
  773.  
  774.   nl = 0;
  775.   while (c = getc(fp), isspace(c))
  776.     if (c == '\n')
  777.       if (nl)
  778.     return (char *) 0;
  779.       else
  780.     ++nl;
  781.   if (c == EOF)
  782.     return (char *) 0;
  783.   ungetc(c, fp);
  784.   p = b = get_ident(fp, ifname);
  785.   while (*p)
  786.     *p = toupper(*p), p++;
  787.   return b;
  788. }
  789.  
  790. void 
  791. get_orient()
  792. {
  793.   xyz_axes       *matp;
  794. #ifdef __STDC__
  795.   char           *err[] =
  796.   {"Null vector", 0};
  797. #else
  798.   char           *err[ERR_MAX];
  799.  
  800.   err[0] = "Null vector";
  801.   err[1] = 0;
  802. #endif
  803.  
  804.   orient_ptr = newa(xyz_axes, 2);
  805.   get_vector(&orient_ptr->x_v);
  806.   if (!vnormalize(&orient_ptr->x_v))
  807.     errorfn(err, fp, ifname);
  808.   get_vector(&orient_ptr->y_v);
  809.   if (!vnormalize(&orient_ptr->y_v))
  810.     errorfn(err, fp, ifname);
  811.   get_vector(&orient_ptr->z_v);
  812.   if (!vnormalize(&orient_ptr->z_v))
  813.     errorfn(err, fp, ifname);
  814.   matp = orient_ptr + 1;
  815.   if (!vinvmat(&orient_ptr->x_v, &orient_ptr->y_v, &orient_ptr->z_v,
  816.            &matp->x_v, &matp->y_v, &matp->z_v))
  817.     err[0] = "Linear dependent vectors", errorfn(err, fp, ifname);
  818. }
  819.  
  820. void
  821. get_pp_obj(fptr)
  822.   file_ptr      fptr;
  823. {
  824.   char           *cp, *com;
  825. #ifdef __STDC__
  826.   char           *err1[] =
  827.   {"Undefined ", 0, 0};
  828.   char           *err2[] =
  829.   {"Invalid command", 0};
  830. #else
  831.   char           *err1[ERR_MAX];
  832.   char           *err2[ERR_MAX];
  833.  
  834.   err1[0] = "Undefined ";
  835.   err1[1] = 0;
  836.   err1[2] = 0;
  837.   err2[0] = "Invalid command";
  838.   err2[1] = 0;
  839. #endif
  840.  
  841. #ifdef THINK_C
  842.  
  843.     /* On the mac, we change the status text to show we're reading text objects */
  844.     if (status_dialog_visible)
  845.         set_status_text("\pReading 3D Text Objects…");
  846.  
  847. #endif
  848.  
  849.   fp = fptr;
  850.   while (com = get_com())
  851.   {
  852.     if (!strcmp(com, "ORIENTATION"))
  853.     {
  854.       get_orient();
  855.     } else if (!strcmp(com, "SCALE"))
  856.     {
  857.       size_ptr = new(xyz_struct);
  858.       get_vector(size_ptr);
  859.     } else if (!strcmp(com, "SPACING"))
  860.     {
  861.       space = get_real(fp, ifname);
  862.     } else if (!strcmp(com, "FONT"))
  863.     {
  864.       cp = get_ident(fp, ifname);
  865.       add_font(cp);
  866.     } else if (!strcmp(com, "ENCODING"))
  867.     {
  868.       cp = get_ident(fp, ifname);
  869.       change_encoding_vector(cp);
  870.     } else if (!strcmp(com, "AT"))
  871.     {
  872.       if (!orient_ptr)
  873.     err1[1] = "ORIENTATION";
  874.       else if (!size_ptr)
  875.     err1[1] = "SCALE";
  876.       else if (space == NULSP)
  877.     err1[1] = "SPACING";
  878.       else if (!font_ptr)
  879.     err1[1] = "FONT";
  880.       else if (!code_ptr)
  881.     err1[1] = "ENCODING";
  882.       if (err1[1])
  883.     errorfn(err1, fp, ifname);
  884.       get_at_text();
  885.     } else
  886.       errorfn(err2, fp, ifname);
  887.   }
  888.   
  889.   
  890. #ifdef THINK_C
  891.  
  892.     /* On the mac, we change the status text to show we're reading objects again */
  893.     if (status_dialog_visible)
  894.         set_status_text("\pReading Objects…");
  895.  
  896. #endif
  897.  
  898. }
  899.  
  900. static void
  901. free_tables()
  902. {
  903.   font           *fp, *fp1;
  904.   character      *chp, *chp1;
  905.  
  906.   fp = fonts_ptr;
  907.   while (fp)
  908.   {
  909.     free(fp->name);
  910.     chp = fp->ch_ptr;
  911.     while (chp)
  912.     {
  913.       free(chp->name);
  914.       chp1 = chp;
  915.       chp = chp->next;
  916.       free(chp1);
  917.     }
  918.     fp1 = fp;
  919.     fp = fp->next;
  920.     free(fp1);
  921.   }
  922. }
  923.  
  924. void
  925. end_pp_get()
  926. {
  927.   free_tables();
  928. }
  929.  
  930. static int
  931. intersect_line(arr, pos, dir, p0, p1, lim)
  932.   real        **arr;
  933.   xy_ptr      pos, dir, p0, p1;
  934.   real          lim;
  935. {
  936.   real            a, b, c, d, e, f, t, det;
  937.   static real     dist[2];
  938.  
  939.   a = dir->x;
  940.   c = dir->y;
  941.   b = p0->x - p1->x;
  942.   d = p0->y - p1->y;
  943.   det = a * d - b * c;
  944.   if (fabs(det) < TINY)
  945.     return 0;
  946.   e = p0->x - pos->x;
  947.   f = p0->y - pos->y;
  948.   t = (a * f - c * e) / det;
  949.   if (t < 0.0 || t >= 1.0)
  950.     return 0;
  951.   dist[0] = (e * d - f * b) / det;
  952.   dist[1] = t;
  953.   *arr = dist;
  954.   return 1;
  955. }
  956.  
  957. static int
  958. intersect_cubic(arr, pos, dir, p0, p1, p2, p3, lim)
  959.   real        **arr;
  960.   xy_ptr      pos, dir, p0, p1, p2, p3;
  961.   real          lim;
  962. {
  963.   static real     x[6];
  964.   real            p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y;
  965.   real            x0, y0, x1, y1, x2, y2, x3, y3;
  966.   real            ax, ay, bx, by, cx, cy;
  967.   real            a, b, c, d, p, q, delta;
  968.   real            t1, t2, t3;
  969.   real            rx, ry, vx, vy;
  970.   real            sqrd, m, tt;
  971.   int             numint, i;
  972.  
  973.   rx = pos->x;
  974.   ry = pos->y;
  975.   vx = dir->x;
  976.   vy = dir->y;
  977.   cx = 3.0 * (p1->x - p0->x);
  978.   cy = 3.0 * (p1->y - p0->y);
  979.   bx = 3.0 * (p2->x - p1->x) - cx;
  980.   by = 3.0 * (p2->y - p1->y) - cy;
  981.   ax = p3->x - p0->x - cx - bx;
  982.   ay = p3->y - p0->y - cy - by;
  983.   a = (vy * ax - vx * ay) * 3.0;
  984.   b = vy * bx - vx * by;
  985.   c = vy * cx - vx * cy;
  986.   d = vy * (p0->x - rx) - vx * (p0->y - ry);
  987.   if (fabs(a) < TINY)
  988.     if (fabs(b) < TINY)
  989.       if (fabs(c) < TINY)
  990.     numint = 0;
  991.       else
  992.       {
  993.     x[1] = t1 = -d / c;
  994.     if (t1 >= 0.0 && t1 < 1.0)
  995.       numint = 1;
  996.     else
  997.       numint = 0;
  998.       }
  999.     else
  1000.     {
  1001.       real            b1;
  1002.       b1 = c / 2.0 / b;
  1003.       delta = b1 * b1 - d / b;
  1004.       if (delta > 0.0)
  1005.       {
  1006.     numint = 0;
  1007.     for (i = -1; i < 2; i += 2)
  1008.     {
  1009.       t1 = -b1 + i * sqrt(delta);
  1010.       if (t1 >= 0.0 && t1 < 1.0)
  1011.       {
  1012.         x[2 * numint + 1] = t1;
  1013.         ++numint;
  1014.       }
  1015.     }
  1016.       } else
  1017.     numint = 0;
  1018.     }
  1019.   else
  1020.   {
  1021.     b /= a;
  1022.     c /= a;
  1023.     d /= a;
  1024.     if (b > 0.0 && c > 0.0 && d > 0.0)
  1025.       return 0.0;
  1026.     if ((d > 0) == (1.0 + 3 * (b + c + d) > 0))
  1027.       if ((c > 0.0) != (1 + 2 * b + c > 0.0))
  1028.     if ((d > 0.0) == (c > 0.0))
  1029.       return 0.0;
  1030.     else;
  1031.       else if (b < -1.0 || b > 0.0)
  1032.     return 0.0;
  1033.       else;
  1034.     p = 3 * (c - b * b);
  1035.     q = b * (2 * b * b - 3 * c) + 3 * d;
  1036.     delta = q * q / 4 + p * p * p / 27;
  1037.     if (delta >= TINY)
  1038.     {
  1039.       real            b1, b2;
  1040.       sqrd = sqrt(delta);
  1041.       b1 = -q / 2.0 + sqrd;
  1042.       b2 = -q / 2.0 - sqrd;
  1043.       t1 = (b1 > 0.0 ? 1.0 : -1.0) * pow(fabs(b1), (double) 1.0 / 3.0) +
  1044.     (b2 > 0.0 ? 1.0 : -1.0) * pow(fabs(b2), (double) 1.0 / 3.0) - b;
  1045.       if (t1 >= 0.0 && t1 < 1.0)
  1046.       {
  1047.     x[1] = t1;
  1048.     numint = 1;
  1049.       } else
  1050.     numint = 0;
  1051.     } else
  1052.     {
  1053.       real            arg;
  1054.       m = sqrt(-p / 3.0);
  1055.       arg = -q / (2 * m * m * m);
  1056.       if (arg < -1.0)
  1057.         arg = -1.0;
  1058.       else if (arg > 1.0)
  1059.         arg = 1.0;
  1060.       tt = acos(arg);
  1061.       numint = 0;
  1062.       for (i = 0; i < 3; i++)
  1063.       {
  1064.     t1 = 2 * m * cos((tt + 2 * M_PI * i) / 3.0) - b;
  1065.     if (t1 >= 0.0 && t1 < 1.0)
  1066.     {
  1067.       x[2 * numint + 1] = t1;
  1068.       ++numint;
  1069.     }
  1070.       }
  1071.     }
  1072.   }
  1073.   for (i = 0; i < numint; i++)
  1074.   {
  1075.     t1 = x[2 * i + 1];
  1076.     t2 = t1 * t1;
  1077.     t3 = t2 * t1;
  1078.     x[2 * i] = fabs(vx) > fabs(vy) ?
  1079.       (ax * t3 + bx * t2 + cx * t1 + p0->x - rx) / vx :
  1080.       (ay * t3 + by * t2 + cy * t1 + p0->y - ry) / vy;
  1081.   }
  1082.   *arr = x;
  1083.   return numint;
  1084. }
  1085.  
  1086. real
  1087. intersect_pp_obj(point_ptr, dir_ptr, bmin_ptr, bmax_ptr, desc_ptr)
  1088.   xyz_ptr      point_ptr, dir_ptr, bmin_ptr, bmax_ptr;
  1089.   void_ptr      desc_ptr;
  1090. {
  1091.   xyz_struct      point, pos, dir;
  1092.   prism          *pp;
  1093.   prismdsc       *pdp;
  1094.   int             ncc, nc, cc, c;
  1095.   ccurve         *cca;
  1096.   curve          *ca;
  1097.   real            dist, inf, sup, in;
  1098.   real            distwin;
  1099.   real            tintm0;
  1100.   int             nintlt0, nintltinf, nintwingt0, icur;
  1101.   int             ccim0, cim0;
  1102.   int             top_down, i;
  1103.   real           *arr;
  1104.   real            tmp;
  1105.  
  1106.   nintlt0 = nintltinf = nintwingt0 = 0;
  1107.   pp = (prism *) desc_ptr;
  1108.   pdp = pp->prismdsc_ptr;
  1109.   vsub(&point, point_ptr, &pp->position);
  1110.   vtransf(&pos, pp->orient_ptr + 1, &point);
  1111.   vtransf(&dir, pp->orient_ptr + 1, dir_ptr);
  1112.   pos.x /= pp->size_ptr->x;
  1113.   pos.y /= pp->size_ptr->y;
  1114.   dir.x /= pp->size_ptr->x;
  1115.   dir.y /= pp->size_ptr->y;
  1116.   if (fabs(dir.z) < TINY)
  1117.   {
  1118.     if (pos.z <= 0.0 || pos.z >= pp->size_ptr->z)
  1119.       return 0.0;
  1120.     else
  1121.       inf = -BIG, sup = BIG;
  1122.   } else
  1123.   {
  1124.     inf = -pos.z / dir.z;
  1125.     sup = (pp->size_ptr->z - pos.z) / dir.z;
  1126.     if (inf > sup)
  1127.       tmp = inf, inf = sup, sup = tmp;
  1128.   }
  1129.   ncc = pdp->n;
  1130.   cca = pdp->ccurve_arr;
  1131.   for (cc = 0; cc < ncc; cc++)
  1132.   {
  1133.     nc = cca[cc].n;
  1134.     ca = cca[cc].curve_arr;
  1135.     for (c = 0; c < nc; c++)
  1136.     {
  1137.       if (ca[c].t == 1)
  1138.     icur = intersect_line(&arr, (xy_ptr) & pos, (xy_ptr) & dir,
  1139.                   &ca[c].p[0], &ca[c + 1].p[0], sup);
  1140.       else
  1141.     icur = intersect_cubic(&arr, (xy_ptr) & pos, (xy_ptr) & dir,
  1142.                    &ca[c].p[0], &ca[c].p[1], &ca[c].p[2],
  1143.                    &ca[c + 1].p[0], sup);
  1144.       for (i = 0; i < icur; i++)
  1145.       {
  1146.     dist = arr[2 * i];
  1147.     if (dist < 0.0)
  1148.       ++nintlt0;
  1149.     if (dist < inf)
  1150.       ++nintltinf;
  1151.     else if (dist > 0.0 && dist < sup)
  1152.     {
  1153.       ++nintwingt0;
  1154.       sup = dist;
  1155.       tintm0 = arr[2 * i + 1];
  1156.       ccim0 = cc;
  1157.       cim0 = c;
  1158.     }
  1159.       }
  1160.     }
  1161.   }
  1162.   if (sup < 0.0)
  1163.     return 0.0;
  1164.   if (!(nintlt0 % 2) || pos.z < 0.0 || pos.z > pp->size_ptr->z)
  1165.   {
  1166.     pp->enter = 1;
  1167.     if (inf > 0.0)
  1168.     {
  1169.       if (nintltinf % 2)
  1170.     top_down = 1, dist = inf;
  1171.       else if (nintwingt0)
  1172.     top_down = 0, dist = sup;
  1173.       else
  1174.     return 0.0;
  1175.     } else
  1176.     {
  1177.       if (nintwingt0)
  1178.     top_down = 0, dist = sup;
  1179.       else
  1180.     return 0.0;
  1181.     }
  1182.   } else
  1183.   {
  1184.     pp->enter = 0;
  1185.     dist = sup;
  1186.     if (nintwingt0)
  1187.       top_down = 0;
  1188.     else
  1189.       top_down = 1;
  1190.   }
  1191.   if (top_down)
  1192.     pp->ccint = -1;
  1193.   else
  1194.   {
  1195.     pp->ccint = ccim0;
  1196.     pp->cint = cim0;
  1197.     pp->tint = tintm0;
  1198.   }
  1199.   pp->dirint = dir;
  1200.   return dist;
  1201. }
  1202.  
  1203. void 
  1204. normal_pp_obj(pos_ptr, desc_ptr, normal_ptr)
  1205.   xyz_ptr pos_ptr;
  1206.   void_ptr desc_ptr;
  1207.   xyz_ptr normal_ptr;
  1208. {
  1209.   real            x0, y0, x1, y1, x2, y2, x3, y3;
  1210.   real            ax, ay, bx, by, cx, cy;
  1211.   real            t, xl, yl;
  1212.   prism          *pp;
  1213.   prismdsc       *pdp;
  1214.   int             cc, c;
  1215.   ccurve         *cca;
  1216.   curve          *ca;
  1217.   xyz_struct      n;
  1218.  
  1219.  
  1220.   pp = (prism *) desc_ptr;
  1221.   pdp = pp->prismdsc_ptr;
  1222.   cc = pp->ccint;
  1223.   c = pp->cint;
  1224.   cca = pdp->ccurve_arr;
  1225.   ca = cca[cc].curve_arr;
  1226.   if (pp->ccint < 0)
  1227.   {
  1228.     n.x = n.y = 0.0;
  1229.     n.z = 1.0;
  1230.   } else if (ca[c].t == 1)
  1231.   {
  1232.     n.x = ca[c + 1].p[0].y - ca[c].p[0].y;
  1233.     n.y = ca[c].p[0].x - ca[c + 1].p[0].x;
  1234.     n.z = 0.0;
  1235.     n.x /= pp->size_ptr->x;
  1236.     n.y /= pp->size_ptr->y;
  1237.   } else
  1238.   {
  1239.     x0 = ca[c].p[0].x;
  1240.     y0 = ca[c].p[0].y;
  1241.     x1 = ca[c].p[1].x;
  1242.     y1 = ca[c].p[1].y;
  1243.     x2 = ca[c].p[2].x;
  1244.     y2 = ca[c].p[2].y;
  1245.     x3 = ca[c + 1].p[0].x;
  1246.     y3 = ca[c + 1].p[0].y;
  1247.     cx = 3 * (x1 - x0);
  1248.     cy = 3 * (y1 - y0);
  1249.     bx = 3 * (x2 - x1) - cx;
  1250.     by = 3 * (y2 - y1) - cy;
  1251.     ax = x3 - x0 - cx - bx;
  1252.     ay = y3 - y0 - cy - by;
  1253.     t = pp->tint;
  1254.     xl = 3 * ax * t * t + 2 * bx * t + cx;
  1255.     yl = 3 * ay * t * t + 2 * by * t + cy;
  1256.     n.x = yl;
  1257.     n.y = -xl;
  1258.     n.z = 0.0;
  1259.     n.x /= pp->size_ptr->x;
  1260.     n.y /= pp->size_ptr->y;
  1261.   }
  1262.   if ((vpint(&pp->dirint, &n) > 0.0) ^ !pp->enter)
  1263.     n.x = -n.x, n.y = -n.y, n.z = -n.z;
  1264.   vtransf(normal_ptr, pp->orient_ptr, &n);
  1265. }
  1266.